package command;

import parser.ChessContentHandlerConstants;
import parser.ParserConstants;

/*
 * This class will define moves that have been made
 * @author Max Joyce (Feb 9, 2010)
 */
public class MoveCommand implements Command {

	private chess.Tile origTile;
	private chess.Tile destTile;
	private boolean movedPreviously;
	protected Command    secondaryCommand;
	
	/*
	 * Constructs the MoveCommand with the original and destination tiles
	 * This class is immutable.
	 * 
	 * <pre>
	 * Max Joyce
	 * -Created class (Feb 9th, 2010)
	 * </pre>
	 */
	public MoveCommand(chess.Tile orig, chess.Tile dest){
		this.destTile=dest;
		this.origTile=orig;
		this.movedPreviously=this.origTile.getPieceHere().hasMoved();
		secondaryCommand = new NoSecondaryCommand();
	}
	@Override
	/*
	 * Performs the actual move
	 * <pre>
	 * Max Joyce
	 * -Created (Feb 9, 2010)
	 * </pre>
	 */
	public void execute() {
		this.origTile.getPieceHere().setMoved(true);
		this.origTile.getPieceHere().move(destTile);
		secondaryCommand.execute();
	}

	@Override
	/*
	 * Undoes the move, reverting to the previous state
	 * <pre>
	 * Max Joyce
	 * -Created (Feb 9, 2010)
	 * </pre>
	 */
	public void undo() {
		secondaryCommand.undo();
		MoveCommand reverseMove = new MoveCommand(destTile,origTile);
		reverseMove.execute();
		this.origTile.getPieceHere().setMoved(movedPreviously);
	}
	
	/*
	 * Outputs the command as a string for output
	 * <pre>
	 * Max Joyce
	 * -Created (Feb 9, 2010)
	 * </pre>
	 */
	public String toString(){
		String output="";
		
		output+="Move: "+origTile.toString()+" to "+destTile.toString();
		
		return output;
	}
	
	public boolean hadMovedPreviously(){
		return movedPreviously;
	}
	
	/**
	 * Allows the addition of a secondary command such as a castle move or a promotion
	 * <pre>
	 * Max Joyce
	 * -Created (Feb 17, 2010)
	 * </pre>
	 */
	public void addSecondaryCommand(Command secondaryCommand){
		if (this.secondaryCommand instanceof NoSecondaryCommand){
			this.secondaryCommand = secondaryCommand;
		}
		else{
			this.secondaryCommand.addSecondaryCommand(secondaryCommand);
		}
	}
	
	public chess.Tile getOrigTile(){
		return this.origTile;
	}
	
	public chess.Tile getDestTile(){
		return this.destTile;
	}
	/**
	 * This method will return a string representation of the command used for importing and
	 * exporting
	 * @return Returns a string representing the object
	 */
	public String exportCode(){
		return "Move:"+origTile.toString()+"to"+destTile.toString() + "with" + this.secondaryCommand.exportCode();
	}
	/**
	 * This method will return a string representation of the command used for saving and
	 * loading
	 * @return Returns a string representing the object
	 */
	@Override
	public String xmlCode() {
		String code = "<" + ParserConstants.ELEMENT_MOVE + ">\n";
		
		code += "\t" + origTile.XMLPointTag(ChessContentHandlerConstants.POINT_1).replaceAll("\n", "\n\t");
		code += "\n";
		code += "\t" + destTile.XMLPointTag(ChessContentHandlerConstants.POINT_2).replaceAll("\n", "\n\t");
		code += "\n";
		code += "</" + ParserConstants.ELEMENT_MOVE + ">\n";
		code += secondaryCommand.xmlCode();
		return code;
	}
	@Override
	public Command getSecondaryCommand() {
		return secondaryCommand;
	}
}
